package com.ruoyi.business.service.impl;

import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruoyi.business.domain.*;
import com.ruoyi.business.mapper.TaskMapper;
import com.ruoyi.business.model.PickerModel;
import com.ruoyi.business.request.ApiTaskReq;
import com.ruoyi.business.response.ApiPlanLayerRes;
import com.ruoyi.business.response.ApiResearchPlanRes;
import com.ruoyi.business.service.IPlanDataService;
import com.ruoyi.business.service.IResearchPlanUserService;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.PageResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.RedisUtils;
import com.ruoyi.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import com.ruoyi.business.mapper.ResearchPlanMapper;
import com.ruoyi.business.service.IResearchPlanService;
import org.springframework.transaction.annotation.Transactional;


import static com.ruoyi.business.constants.JetCacheConstant.PLAN_LAYER_CACHE_NAME;


/**
 * 调研计划Service业务层处理
 *
 * @author Eric
 * @date 2024-03-20
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ResearchPlanServiceImpl extends ServiceImpl<ResearchPlanMapper, ResearchPlan> implements IResearchPlanService {

    private final IPlanDataService planDataService;

    private final IResearchPlanUserService researchPlanUserService;
    private final TaskMapper taskMapper;
    private final ISysUserService userService;

    @Override
    public List<Map<String, Object>> select() {
        List<ResearchPlan> list = this.list(Wrappers.lambdaQuery(ResearchPlan.class)
                .orderByDesc(BaseEntity::getCreateTime));
        List<Map<String, Object>> result = Lists.newArrayListWithCapacity(list.size());
        if (CollUtil.isNotEmpty(list)) {
            for (ResearchPlan researchPlan : list) {
                Map<String, Object> map = Maps.newHashMap();
                map.put("id", researchPlan.getId());
                map.put("name", researchPlan.getPlanName());
                result.add(map);
            }
        }
        return result;
    }

    @Override
    public PageResult<ApiResearchPlanRes> pageResearchPlan(ApiTaskReq req) {
        PageUtils.startPage();
        return null;
    }

    @Override
    public List<Map<String, Object>> selectByUserId(Long userId) {
        return baseMapper.selectByUserId(userId);
    }

    @Override
    public List<Map<String, Object>> selectValidityPeriodByUserId(Long userId) {
        return baseMapper.selectValidityPeriodByUserId(userId);
    }

    @Override
    public List<Map<String, Object>> selectValidityPeriodNotTaskByUserId(Long userId) {
        return baseMapper.selectValidityPeriodNotTaskByUserId(userId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updatePlan(ResearchPlan researchPlan) {
        //---------计划用户处理------------------
        // 先查出旧用户
        List<ResearchPlanUser> oldPlanUserList = researchPlanUserService.list(Wrappers.lambdaQuery(ResearchPlanUser.class)
                .eq(ResearchPlanUser::getResearchPlanId, researchPlan.getId()));
        List<Long> oldPlanUserIdList = oldPlanUserList.stream().map(ResearchPlanUser::getUserId).collect(Collectors.toList());

        Long[] userIds = researchPlan.getUserIds();
        // 存储新用户
        List<Long> addPlanUserIdList = Lists.newArrayList();
        for (Long userId : userIds) {
            if (oldPlanUserIdList.contains(userId)) {
                oldPlanUserIdList.remove(userId);
            } else {
                addPlanUserIdList.add(userId);
            }
        }
        checkDeletePlanUser(oldPlanUserIdList, researchPlan.getId());
        if (CollUtil.isNotEmpty(oldPlanUserList)) {
            for (Long userId : oldPlanUserIdList) {
                researchPlanUserService.remove(Wrappers.lambdaQuery(ResearchPlanUser.class)
                        .eq(ResearchPlanUser::getResearchPlanId, researchPlan.getId())
                        .eq(ResearchPlanUser::getUserId, userId));
            }
        }
        if (CollUtil.isNotEmpty(addPlanUserIdList)) {
            List<ResearchPlanUser> planUsers = Lists.newArrayListWithCapacity(addPlanUserIdList.size());
            for (Long userId : addPlanUserIdList) {
                ResearchPlanUser planUser = ResearchPlanUser.builder()
                        .userId(userId)
                        .researchPlanId(researchPlan.getId())
                        .build();
                planUsers.add(planUser);
            }
            if (CollUtil.isNotEmpty(planUsers)) {
                researchPlanUserService.saveBatch(planUsers);
            }
        }

        List<Long[]> layers = researchPlan.getLayers();
        planDataService.remove(Wrappers.lambdaQuery(PlanData.class)
                .eq(PlanData::getResearchPlanId, researchPlan.getId()));
        List<PlanData> planDataList = Lists.newArrayList();
        if (CollUtil.isNotEmpty(layers)) {
            for (Long[] layer : layers) {
                PlanData planData = new PlanData();
                planData.setResearchPlanId(researchPlan.getId());
                planData.setDataServerId(layer[1]);
                planData.setDataTypeId(layer[0]);
                planDataList.add(planData);
            }
        }
        if (CollUtil.isNotEmpty(planDataList)) {
            planDataService.saveBatch(planDataList);
        }
        this.updateById(researchPlan);
        String cacheKey = StrUtil.format("{}{}", PLAN_LAYER_CACHE_NAME, researchPlan.getId());
        RedisUtils.deleteObject(cacheKey);


        return true;
    }
    
    private void checkDeletePlanUser(List<Long> oldPlanUserIdList, Long planId) {
        if (CollUtil.isNotEmpty(oldPlanUserIdList)) {
            for (Long userId : oldPlanUserIdList) {
                List<Map<String, Object>> list = taskMapper.getPlanTaskUser(planId, userId);
                if (CollUtil.isNotEmpty(list)) {
                    SysUser user = userService.getById(userId);
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append("用户：").append(user.getUserName());
                    stringBuilder.append("已分配以下任务：[");
                    for (Map<String, Object> map : list) {
                        String taskName = MapUtil.getStr(map, "task_name");
                        stringBuilder.append(taskName).append(",");
                    }
                    stringBuilder.deleteCharAt(stringBuilder.lastIndexOf(","));
                    stringBuilder.append("]");
                    stringBuilder.append("不能删除");
                    throw new ServiceException(stringBuilder.toString());
                }
            }

        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean savePlan(ResearchPlan researchPlan) {
        this.save(researchPlan);
        List<Long[]> layers = researchPlan.getLayers();
        if (CollUtil.isNotEmpty(layers)) {
            List<PlanData> planDataList = Lists.newArrayListWithCapacity(layers.size());
            for (Long[] layer : layers) {
                PlanData planData = new PlanData();
                planData.setResearchPlanId(researchPlan.getId());
                planData.setDataServerId(layer[1]);
                planData.setDataTypeId(layer[0]);
                planDataList.add(planData);
            }
            if (CollUtil.isNotEmpty(planDataList)) {
                planDataService.saveBatch(planDataList);
            }
        }
        Long[] userIds = researchPlan.getUserIds();
        if (ArrayUtil.isNotEmpty(userIds)) {
            List<ResearchPlanUser> planUsers = Lists.newArrayListWithCapacity(userIds.length);
            for (Long userId : userIds) {
                ResearchPlanUser planUser = ResearchPlanUser.builder()
                        .userId(userId)
                        .researchPlanId(researchPlan.getId())
                        .build();
                planUsers.add(planUser);
            }
            if (CollUtil.isNotEmpty(planUsers)) {
                researchPlanUserService.saveBatch(planUsers);
            }
        }
        return true;
    }

    @Override
    public ResearchPlan getResearchPlanInfo(Long id) {
        ResearchPlan researchPlan = this.getById(id);
        if (researchPlan != null) {
            List<PlanData> planDataList = planDataService.list(Wrappers.lambdaQuery(PlanData.class)
                    .eq(PlanData::getResearchPlanId, id));
            if (CollUtil.isNotEmpty(planDataList)) {
                List<Long[]> layers = Lists.newArrayList();
                for (PlanData planData : planDataList) {
                    Long[] layer = new Long[2];
                    layer[0] = planData.getDataTypeId();
                    layer[1] = planData.getDataServerId();
                    layers.add(layer);
                }
                researchPlan.setLayers(layers);
            }
            List<ResearchPlanUser> planUserList = researchPlanUserService.list(Wrappers.lambdaQuery(ResearchPlanUser.class)
                    .eq(ResearchPlanUser::getResearchPlanId, researchPlan.getId()));
            if (CollUtil.isNotEmpty(planUserList)) {
                List<Long> userList = Lists.newArrayList();
                for (ResearchPlanUser planUser : planUserList) {
                    userList.add(planUser.getUserId());
                }
                researchPlan.setUserIds(ArrayUtil.toArray(userList, Long.class));
            }
        }
        return researchPlan;
    }

    @Override
    public List<ApiPlanLayerRes> getPlanLayer(Long researchPlanId) {
        String cacheKey = StrUtil.format("{}{}", PLAN_LAYER_CACHE_NAME, researchPlanId);
        List<ApiPlanLayerRes> list = RedisUtils.getCacheObject(cacheKey);
        if (CollUtil.isEmpty(list)) {
            list = planDataService.getPlanLayerByPlanId(researchPlanId);
            RedisUtils.deleteObject(cacheKey);
            RedisUtils.setCacheObject(cacheKey, list, Duration.ofMinutes(60));
        }
        return list;
    }

    @Override
    public List<PickerModel> getPlanPickerLayer(Long researchPlanId) {
//        String cacheKey = StrUtil.format(PLAN_LAYER_CACHE_KEY, SecurityUtils.getUserId());
//        List<PickerModel> list = RedisUtils.getCacheObject(cacheKey);
//        if (CollUtil.isEmpty(list)) {
        List<PickerModel> list = Lists.newArrayList();
//            List<Map<String, Object>>  planList = baseMapper.selectByUserId(SecurityUtils.getUserId());
        ResearchPlan researchPlan = this.getById(researchPlanId);
        if (researchPlan != null) {
//                for (Map<String, Object> map : planList) {
            Long id = researchPlan.getId();//MapUtil.getLong(map, "id");
            String planName = researchPlan.getPlanName();//MapUtil.getStr(map, "plan_name");
            PickerModel pickerModelOne = new PickerModel();
            pickerModelOne.setId(id);
            pickerModelOne.setLabel(planName);
            List<PickerModel> pickerModelTwo = planDataService.getPlanPickerLayerByPlanId(id);
            if (CollUtil.isEmpty(pickerModelTwo)) {
                return Lists.newArrayList();
            }
            for (PickerModel pickerModel : pickerModelTwo) {
                List<PickerModel> pickerModelThree = planDataService.getPlanPickerLayerByPlanId1(id, pickerModel.getId());
                pickerModel.setChildren(pickerModelThree);
            }
            pickerModelOne.setChildren(pickerModelTwo);
            list.add(pickerModelOne);
//                }
//                RedisUtils.deleteObject(cacheKey);
//                RedisUtils.setCacheObject(cacheKey, list, Duration.ofHours(RandomUtil.randomInt(13, 24)));
//            }
        }
        return list;
    }

    @Override
    public List<ResearchPlan> selectEndPlan() {
        return baseMapper.selectEndPlan();
    }

    @Override
    public List<Map<String, Object>> selectNotTaskPlanByUserId(Long userId) {
        return baseMapper.selectNotTaskPlanByUserId(userId);
    }
}
